package controllers.filter;


import com.google.common.collect.Lists;
import com.tom.basic.service.ServiceResult;
import org.apache.log4j.MDC;
import play.db.jpa.JPA;
import play.mvc.Before;
import play.mvc.Catch;
import play.mvc.Controller;
import play.mvc.Finally;
import support.LogUtils;
import support.exception.ParamsValidateException;

import java.util.List;
import java.util.Map;
import java.util.UUID;

public class FilterAdminPortal extends Controller {


    private static final ThreadLocal<Long> TIME_ESTIMATE = new ThreadLocal<>();

    // highest filter
    @Before(priority = 0)
    public static void before1() {
        response.setHeader("Access-Control-Allow-Origin", "*");
        response.setHeader("Access-Control-Allow-Methods", "*");
        response.setHeader("Access-Control-Max-Age", "3600");
        response.setHeader("Access-Control-Allow-Headers", "*");
        response.setHeader("Access-Control-Allow-Credentials", "true");
        MDC.put("logId", UUID.randomUUID().toString());
        TIME_ESTIMATE.set(System.nanoTime());
        if (request.method.equals("OPTIONS")) {
            renderJSON(ServiceResult.asSuccess(""));
        }
    }

    @Finally(priority = 0)
    public static void finallyExecute() {
        long start = TIME_ESTIMATE.get();
        long used = (System.nanoTime() - start) / 1000000;
        String operator = "no";
        String userAgent = "unknow";
        if (request.headers != null && request.headers.get("user-agent") != null) {
            userAgent = request.headers.get("user-agent").value();
        }

        LogUtils.ACCESS_LOGGER.info(String.format("operator=%s,path=%s,remote=%s,domain=%s,used=%d ms,user-agent={%s},params=%s, " +
                        "response=[%s]", operator, request.path, request.remoteAddress, request.domain, used, userAgent, getParams(),
                new String(response.out.toByteArray())));
    }

    @Finally(priority = Integer.MAX_VALUE)
    public static void removeThreadLocal() {
        try {
            TIME_ESTIMATE.remove();
        } catch (Exception e) {
            LogUtils.ERROR_LOGGER.error("execute exception", e);
        }
        try {
            MDC.clear();
        } catch (Exception e) {
            LogUtils.ERROR_LOGGER.error("execute exception", e);
        }
    }

    static List<Class> clazzWarn = Lists.newArrayList(ParamsValidateException.class);

    @Catch(Exception.class)
    public static void exception(Throwable throwable) {
        JPA.setRollbackOnly();
        Class cla = throwable.getClass();
        if (clazzWarn.contains(cla)) {
            LogUtils.ERROR_LOGGER.warn("Mgr encounter error1!req params=" + getParams(), throwable);
        } else {
            LogUtils.ERROR_LOGGER.error("Mgr encounter error2!req params=" + getParams(), throwable);
        }
        renderJSON(ServiceResult.asFail(throwable.getMessage()));
    }

    public static StringBuilder getParams() {
        StringBuilder sb = new StringBuilder();
        Map<String, String> allParams = request.params.allSimple();
        for (String dataKey : allParams.keySet()) {
            sb.append("\"" + dataKey + "\":\"" + request.params.allSimple().get(dataKey) + "\",");
        }
        return sb;
    }

}
